/**
* File: War3Source_Risen.sp
* Description: The Risen race for War3Source
* Author(s): xDr.HaaaaaaaXx & Revan
*/

#pragma semicolon 1
#include <sourcemod>
#include <sdktools_tempents>
#include <sdktools_functions>
#include <sdktools_tempents_stocks>
#include <sdktools_entinput>
#include <sdktools_sound>

#include "W3SIncs/War3Source_Interface"

// War3Source stuff
new thisRaceID, SKILL_HP, SKILL_INFECT, SKILL_SPAWN, ULT_SPEED;

// Chance/Data Arrays
new Float:InfectChance[7] = { 0.0, 0.30, 0.40, 0.45, 0.50, 0.55, 0.60 };
new Float:SpawnChance[7] = { 0.0, 0.30, 0.40, 0.55, 0.60, 0.65, 0.75 };
new Float:UltDelay[7] = { 0.0, 3.0, 4.0, 5.5, 6.2, 7.0, 10.0 };
new Float:xSpeed[7] = { 0.0, 1.1, 1.2, 1.4, 1.4, 1.5, 1.6 };
new Float:BounceDuration[6] = { 0.0, 6.5, 7.0, 8.5, 9.0, 9.0 };
new HealthADD[7] = { 0, 20, 50, 80, 100, 150, 200 };
new bonus[7] = { 0, 1, 2, 3, 4, 4, 5 };
new bool:Infected[MAXPLAYERS];
new bool:InfectedBy[MAXPLAYERS];
new bool:bIsEntangled[MAXPLAYERS];

// Sounds
new String:spawn[] = "npc/zombie_poison/pz_call1.wav";
new String:attack[] = "npc/zombie/claw_strike2.wav";
new String:ultsnd[] = "npc/zombie/zombie_alert1.wav";
new String:fleshi[] = "physics/flesh/flesh_bloody_break.wav";
new Glow;
public Plugin:myinfo = 
{
	name = "Lustful Zombie",
	author = "xDr.HaaaaaaaXx & Revan",
	description = "Zombie Race for War3Source.",
	version = "1.0.0.0",
	url = ""
};

public OnPluginStart()
{
	HookEvent( "player_death", PlayerDeathEvent );
	HookEvent("player_hurt", EventPlayerHurt, EventHookMode_Pre);
	CreateTimer( 1.0, CalcInfect, _, TIMER_REPEAT );
}

public OnMapStart()
{
	Glow=PrecacheModel("materials/sprites/redglow3.vmt");
	War3_PrecacheSound( spawn );
	War3_PrecacheSound( attack );
	War3_PrecacheSound( ultsnd );
	War3_PrecacheSound( fleshi );
	//PrecacheModel( "models/Zombie/Classic.mdl", true );
}

public OnWar3PluginReady()
{
	thisRaceID = War3_CreateNewRace( "Lustful Zombie", "tsm" );
	SKILL_HP = War3_AddRaceSkill( thisRaceID, "Ferocious", "Only headshots are able to kill you.", false, 5 );	
	SKILL_INFECT = War3_AddRaceSkill( thisRaceID, "Braineater", "Get More Health at spawn, do more damage", false, 5 );	
	SKILL_SPAWN = War3_AddRaceSkill( thisRaceID, "Zombie Conviction", "Raise your speed for a few of seconds if you take damage.", false, 5 );
	ULT_SPEED = War3_AddRaceSkill( thisRaceID, "Indestructible food desire", "Chance to extend your lifetime for a few seconds before you are finaly dead", true, 5 );	
	War3_CreateRaceEnd( thisRaceID );
}

public InitPassiveSkills( client )
{
	if( War3_GetRace( client ) == thisRaceID )
	{
		new hp_level = War3_GetSkillLevel( client, thisRaceID, SKILL_INFECT );
		if( hp_level > 0 )
		{
			//War3_SetMaxHP( client, HealthADD[hp_level] );
			War3_SetBuff(client, iAdditionalMaxHealth, thisRaceID, HealthADD[hp_level] );
			if(IsPlayerAlive(client))
			{
				//SetEntityHealth(client,HealthADD[hp_level]); 
				PrintToChat(client,"BRAAAIIINSSSS!");
			}
		}
		W3SetPlayerColor(client,thisRaceID,255,0,0,255,1);
		PrintToConsole(client,"you are a braineater!");
		//SetEntityModel( client, "models/Zombie/Classic.mdl" );
	}
}

public Action:EventPlayerHurt(Handle:event, const String:name[],bool:dontBroadcast)
{
	new hitgroup = GetEventInt(event, "hitgroup");
	new victim = GetClientOfUserId(GetEventInt(event, "userid"));
	new attacker = GetClientOfUserId(GetEventInt(event, "attacker"));
	new damage = GetEventInt(event, "dmg_health");
	if( War3_GetRace( victim ) == thisRaceID )
		{
			new skill_level = War3_GetSkillLevel( victim, thisRaceID, SKILL_HP );
			if( skill_level > 0 && victim > 0 && ValidPlayer( attacker, true ))
			{
				if (hitgroup != 1)
				{
					SetEntityHealth(victim,GetClientHealth(victim)+damage+bonus[skill_level]);
					new Float:vicpos[3];
					GetClientEyePosition(victim, vicpos);
					TE_SetupGlowSprite(vicpos, Glow, 1.0, 1.0, 255);
					TE_SendToAll();
					Blood( victim );
					PrintCenterText(attacker,"Aim for the head to kill the Zombie!");
					PrintCenterText(victim,"You get Stronger!");
					PrintHintText(attacker,"Aim for the head\notherwise your target will only get stronger");
					EmitSoundToClient(victim, fleshi, SOUND_FROM_PLAYER, SNDCHAN_AUTO, SNDLEVEL_RAIDSIREN);
				}
			}
		}
	return Plugin_Continue;
}

public OnRaceChanged( client,oldrace,newrace )
{
	if( newrace != thisRaceID )
	{
		W3ResetPlayerColor(client,thisRaceID);
		War3_SetBuff( client, fMaxSpeed, thisRaceID, 1.0 );
		War3_SetBuff( client, fSlow, thisRaceID, 1.0 );
		War3_WeaponRestrictTo( client, thisRaceID, "" );
	}
	else
	{
		War3_WeaponRestrictTo( client, thisRaceID, "weapon_knife" );
		if( IsPlayerAlive( client ) )
		{
			InitPassiveSkills( client );
		}
	}
}

public OnSkillLevelChanged( client, race, skill, newskilllevel )
{
	InitPassiveSkills( client );
}

public OnWar3EventSpawn( client )
{
	new race = War3_GetRace( client );
	if( race == thisRaceID )
	{
		War3_SetBuff( client, fMaxSpeed, thisRaceID, 1.10 );
		InitPassiveSkills( client );
		EmitSoundToAll( spawn, client );
		SetEntProp(client,Prop_Send,"m_ArmorValue",300);
		SetEntProp(client,Prop_Send,"m_bHasHelmet",1,1);
	}
	Infected[client] = false;
}

public OnWar3EventPostHurt( victim, attacker, damage )
{
	if( W3GetDamageIsBullet() && ValidPlayer( victim, true ) && ValidPlayer( attacker, true ) && GetClientTeam( victim ) != GetClientTeam( attacker ) )
	{
		if( War3_GetRace( attacker ) == thisRaceID )
		{
			new skill_level = War3_GetSkillLevel( attacker, thisRaceID, SKILL_INFECT );
			if( !Hexed( attacker, false ) && GetRandomFloat( 0.0, 1.0 ) <= InfectChance[skill_level] && !W3HasImmunity( victim, Immunity_Skills  ) )
			{
				new String:NameAttacker[64];
				GetClientName( attacker, NameAttacker, 64 );
				
				new String:NameVictim[64];
				GetClientName( victim, NameVictim, 64 );

				PrintToChat( attacker, "\03You have infected %s!!", NameVictim );
				PrintToChat( victim, "\x03You have been INFECTED by %s's Infectious Bite!", NameAttacker );
				
				Blood( victim );
				
				War3_DealDamage( victim, 40, attacker, DMG_BULLET, "weapon_knife" );
				
				EmitSoundToAll( attack, victim );
				EmitSoundToAll( attack, attacker );
				
				Infected[victim] = true;
				CreateTimer( BounceDuration[skill_level], InfectedStop, victim );
			}
		}
		if( War3_GetRace( victim ) == thisRaceID )
		{
			new skill_level2 = War3_GetSkillLevel( attacker, thisRaceID, SKILL_SPAWN );
			if( !Hexed( victim, false ) && skill_level2 > 0 && bIsEntangled[victim])
			{
				War3_SetBuff( victim, fMaxSpeed, thisRaceID, xSpeed[skill_level2] );
				War3_SetBuff( victim, fAttackSpeed, thisRaceID, 1.75 );
				Blood( victim );
				CreateTimer( 1.85, Normal1, victim );
				PrintCenterText(victim,"Zombie Conviction!");
				new Float:iVec[3];
				GetClientEyePosition(victim,iVec);
				iVec[2]-30.0;
				TE_SetupBeamRingPoint(iVec, 10.0, 68.0, Glow, Glow, 0, 1, 1.20, 50.0, 0.5, {255,120,120,255}, 10, 0);
				TE_SendToAll();
				bIsEntangled[victim]=false;
				//TE_SetupBeamRingPoint( iVec,74.0,75.0,Beam2,Beam2,0,15,5.0,60.0,12.0,{0,0,255,255},1,0);
			}
		}
	}
}
public Action:Normal1( Handle:timer, any:client )
{
	War3_SetBuff( client, fMaxSpeed, thisRaceID, 1.10 );
	War3_SetBuff( client, fAttackSpeed, thisRaceID, 1.00 );
	bIsEntangled[client]=true;
}

public Action:InfectedStop( Handle:timer, any:client )
{
	Infected[client] = false;
}

public Action:CalcInfect( Handle:timer, any:userid )
{
	for( new i = 1; i <= MaxClients; i++ )
	{
		if( ValidPlayer( i, true ) )
		{
			if( Infected[i] == true )
			{
				if( IsPlayerAlive( i ) && !W3HasImmunity( i, Immunity_Skills  ) )
				{
					new dealer = InfectedBy[i];
					War3_DealDamage( i, 1, dealer, DMG_SLASH, "infect" );
					new Float:spos[3];
					new Float:epos[3];
					GetClientAbsOrigin(i,epos);
					GetClientAbsOrigin(i,spos);
					epos[2]+=80.0;
					TE_SetupBeamPoints(spos, epos, Glow, Glow, 1, 5, 0.35, 1.0, 30.0, 2, 20.0, {255,30,30,255}, 10);
					TE_SendToAll();
				}
			}
		}
	}
}

public OnUltimateCommand( client, race, bool:pressed )
{
	if( race == thisRaceID && pressed && IsPlayerAlive( client ) )
	{
		PrintHintText(client,"failed:\n-Passive Ultimate");
	}
}

public PlayerDeathEvent( Handle:event, const String:name[], bool:dontBroadcast )
{
	new client = GetClientOfUserId( GetEventInt( event, "userid" ) );
	if( War3_GetRace( client ) == thisRaceID && client != 0 )
	{
		new skill_spawn = War3_GetSkillLevel( client, thisRaceID, ULT_SPEED );
		if( skill_spawn > 0 && GetRandomFloat( 0.0, 1.0 ) <= SpawnChance[skill_spawn] )
		{
			CreateTimer( UltDelay[skill_spawn], Spawn, client );
			PrintToChat(client,"Respawn soon!");
		}
	}
	Infected[client] = false;
}

public Action:Spawn( Handle:timer, any:client )
{
	War3_SpawnPlayer( client );
	PrintToChat( client, "You have risen from the grave!" );
	IgniteEntity(client,3.5);
	CreateTimer( 0.5, shealth, client );
}

public Action:shealth( Handle:timer, any:client )
{
	War3_DealDamage( client, 25, client, DMG_SLASH, "escape" );
	Blood( client );
}

Action:Blood( client )
{
	new Float:Pos[3];
	GetClientAbsOrigin( client, Pos );
	new blood = CreateEntityByName( "env_blood" );
	if( blood )
	{
		DispatchKeyValue( blood, "color", "0" );
		DispatchKeyValue( blood, "amount", "50" );
		DispatchKeyValue( blood, "spawnflags", "109" );
		DispatchSpawn( blood );
		TeleportEntity( blood, Pos, NULL_VECTOR, NULL_VECTOR );
		AcceptEntityInput( blood, "emitblood" );
	}
}